package com.css.zfzx.sjcj.modules.jobschedule.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.css.bpm.platform.constants.PlatformConstants;
import com.css.bpm.platform.utils.*;
import com.css.zfzx.sjcj.common.division.service.MyDivisionService;
import com.css.zfzx.sjcj.common.vo.DivisionVo;
import com.css.zfzx.sjcj.config.MyX509TrustManager;
import com.css.zfzx.sjcj.modules.jobschedule.entity.SendDataRes;
import com.css.zfzx.sjcj.modules.jobschedule.entity.enums.ScheduleReportEnum;
import com.css.zfzx.sjcj.modules.jobschedule.entity.po.JobScheduleReportPO;
import com.css.zfzx.sjcj.modules.jobschedule.entity.vo.JobScheduleReportVO;
import com.css.zfzx.sjcj.modules.jobschedule.entity.vo.QueryDataVO;
import com.css.zfzx.sjcj.modules.jobschedule.entity.vo.QueryRespondVO;
import com.css.zfzx.sjcj.modules.jobschedule.entity.vo.ScheduleInfoVo;
import com.css.zfzx.sjcj.modules.jobschedule.repository.JobScheduleNativeRepository;
import com.css.zfzx.sjcj.modules.jobschedule.repository.JobScheduleRepository;
import com.css.zfzx.sjcj.modules.jobschedule.service.JobScheduleReportService;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;
import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSession;
import javax.net.ssl.TrustManager;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import javax.annotation.PostConstruct;
import java.nio.charset.StandardCharsets;
import java.time.LocalDateTime;
import java.util.*;

/**
 * @Description: pc-statistics
 * @Author: lhl
 * @CreateDate: 2021/8/17 9:17
 */
@Service
public class JobScheduleReportServiceImpl implements JobScheduleReportService {

    private final JobScheduleNativeRepository<JobScheduleReportPO> jobScheduleNativeRepository;
    private final JobScheduleRepository jobScheduleRepository;
    private final MyDivisionService divisionService;

    @Autowired
    public JobScheduleReportServiceImpl(JobScheduleNativeRepository<JobScheduleReportPO> jobScheduleNativeRepository,
                                        JobScheduleRepository jobScheduleRepository,
                                        MyDivisionService divisionService) {
        this.jobScheduleNativeRepository = jobScheduleNativeRepository;
        this.jobScheduleRepository = jobScheduleRepository;
        this.divisionService = divisionService;
    }

    private Logger logger = LoggerFactory.getLogger(getClass());
    /**
     * 库里所有省级区划的集合
     * DivisionVo：
     * provinceCode 省级编码
     * provinceName 省级名称
     */
    public static List<DivisionVo> provinceList = new ArrayList<>();
    /**
     * 枚举所有菜单的集合
     */
    public static List<ScheduleReportEnum> enumList = new ArrayList<>();
    /**
     * 枚举所有上报任务的集合
     */
    public static List<ScheduleReportEnum> reportList = new ArrayList<>();

    @PostConstruct
    public void init() {
        provinceList = divisionService.getAllProvince();
        enumList = Arrays.asList(ScheduleReportEnum.values());
        reportList = ScheduleReportEnum.getReportList();
    }

    @Override
    public List<QueryRespondVO> findPcSchedule(String usersId) {
        List<JobScheduleReportPO> reportPOList = jobScheduleRepository.findAll();
        List<QueryRespondVO> queryRespondVOS = new ArrayList<>();
        for (DivisionVo divisionVo : provinceList) {
            String provinceName = divisionVo.getProvinceName();
            String provinceCode = divisionVo.getProvinceCode();
            QueryRespondVO queryRespondVO = new QueryRespondVO();
            queryRespondVO.setDivisionCode(provinceCode);
            queryRespondVO.setDivisionName(provinceName);
            List<QueryDataVO> dataVOS = new ArrayList<>();
            for (ScheduleReportEnum task : ScheduleReportEnum.values()) {
                String taskCode = task.getTaskId();
                QueryDataVO queryDataVO = new QueryDataVO();
                queryDataVO.setTaskCode(taskCode);
                queryDataVO.setTaskName(task.getTaskName());
                for (JobScheduleReportPO reportPO : reportPOList) {
                    if (provinceCode.equals(reportPO.getDivisionCode()) && taskCode.equals(reportPO.getTaskCode())) {
                        queryDataVO.setPercentage(reportPO.getPercentage());
                        queryDataVO.setQuantity(reportPO.getQuantity());
                        break;
                    }
                }
                if(reportList.contains(task)){
                    if (StringUtils.isEmpty(queryDataVO.getQuantity()) || "null".equals(queryDataVO.getQuantity())) {
                        queryDataVO.setQuantity("无此任务");
                    }
                    if (StringUtils.isEmpty(queryDataVO.getPercentage()) || "null".equals(queryDataVO.getPercentage())) {
                        queryDataVO.setPercentage("无此任务");
                    }
                }
                dataVOS.add(queryDataVO);
            }
            queryRespondVO.setDataVOS(dataVOS);
            queryRespondVOS.add(queryRespondVO);
        }
        return queryRespondVOS;
    }

    public SendDataRes combinationData(ScheduleReportEnum anEnum, List<JobScheduleReportPO> reportPOList) {
        SendDataRes sendDataRes = new SendDataRes();
        sendDataRes.setDepType(9);
        sendDataRes.setTaskType(5);
        sendDataRes.setDataTime(LocalDateTime.now());
        List<ScheduleInfoVo> dataList = new ArrayList<>();
        //全国的数据
        ScheduleInfoVo infoVo = new ScheduleInfoVo();
        double quantity = 0.0;
        double percentage = 0.0;
        boolean isNaNA=true;
        boolean isNaNB=true;
        int count = 0;
        infoVo.setId(anEnum.getReportId());
        infoVo.setCode("0");
        for (JobScheduleReportPO po : reportPOList) {
            String quantity1 = po.getQuantity();
            String percentage1 = po.getPercentage();
            // if (StringUtils.isEmpty(quantity1) || "null".equals(quantity1)) {
            //     quantity1 = "0";
            // }
            // if (StringUtils.isEmpty(percentage1) || "null".equals(percentage1)) {
            //     percentage1 = "0";
            // }
            if (StringUtils.isNotEmpty(quantity1)&&!"null".equals(quantity1)) {
                isNaNB=false;
                quantity = quantity + Double.valueOf(quantity1);
            }
            if (StringUtils.isNotEmpty(percentage1)&&!"null".equals(percentage1)) {
                isNaNA=false;
                percentage = percentage + Double.valueOf(percentage1);
                count++;
            }
        }
        if (!isNaNB) {
            infoVo.setAllCount((int) quantity);
            infoVo.setFinishCount((int) quantity);
        }else {
            infoVo.setAllCount(null);
            infoVo.setFinishCount(null);
        }
        if (!isNaNA) {
            infoVo.setPercent((float) percentage / count / 100);
        }else {
            infoVo.setPercent(null);
        }
        dataList.add(infoVo);
        //省级的数据
        for (DivisionVo vo : provinceList) {
            isNaNA=true;
            isNaNB=true;
            ScheduleInfoVo infoVo1 = new ScheduleInfoVo();
            infoVo1.setId(anEnum.getReportId());
            double quantity1 = 0.0;
            double percentage1 = 0.0;
            count = 0;
            for (JobScheduleReportPO po : reportPOList) {
                infoVo1.setCode(vo.getProvinceCode().substring(0, 2));
                String quantity2 = po.getQuantity();
                String percentage2 = po.getPercentage();
                // if (StringUtils.isEmpty(quantity2) || "null".equals(quantity2)) {
                //     quantity2 = "0";
                // }
                // if (StringUtils.isEmpty(percentage2) || "null".equals(percentage2)) {
                //     percentage2 = "0";
                // }
                if ("41".equals(anEnum.getTaskId())) {//地震
                    if (vo.getProvinceCode().equals(po.getDivisionCode())) {
                        if (StringUtils.isNotEmpty(quantity2)&&!"null".equals(quantity2)) {
                            quantity1 = quantity1 + Double.valueOf(quantity2);
                            isNaNB=false;
                        }
                        if (StringUtils.isNotEmpty(percentage2)&&!"null".equals(percentage2)) {
                            percentage1 = percentage1 + Double.valueOf(percentage2);
                            isNaNA=false;
                            count++;
                        }
                    }
                } else {
                    if (vo.getProvinceCode().equals(po.getDivisionCode())
                            && anEnum.getTaskId().equals(po.getTaskCode())) {
                        if (StringUtils.isNotEmpty(quantity2)&&!"null".equals(quantity2)) {
                            quantity1 = Double.valueOf(quantity2);
                            isNaNB=false;
                        }
                        if (StringUtils.isNotEmpty(percentage2)&&!"null".equals(percentage2)) {
                            percentage1 = Double.valueOf(percentage2);
                            isNaNA=false;
                        }
                        count++;
                        break;
                    }
                }

            }
            if (!isNaNB) {
                infoVo1.setAllCount((int) quantity1);
                infoVo1.setFinishCount((int) quantity1);
            }else {
                infoVo1.setAllCount(null);
                infoVo1.setFinishCount(null);
            }
            if (!isNaNA) {
                infoVo1.setPercent((float) percentage1 / count / 100);
            }else {
                infoVo1.setPercent(null);
            }
            dataList.add(infoVo1);
        }
        sendDataRes.setData(dataList);
        return sendDataRes;
    }

    @Override
    public void httpsSendCommonMethod(String usersId) {
        logger.info("##########################   上报进度发送  start");
        List<JobScheduleReportPO> reportPOList = jobScheduleRepository.findAllByReportIdIsNotNull();
        List<ScheduleReportEnum> reportList = ScheduleReportEnum.getReportList();
        for (ScheduleReportEnum anEnum : reportList) {
            String taskId = anEnum.getTaskId();
            String taskName = anEnum.getTaskName();
            List<JobScheduleReportPO> reportPOS = new ArrayList<>();
            for (JobScheduleReportPO po : reportPOList) {
                if (taskId.equals(po.getTaskCode())) {
                    po.setIsHasReport(PlatformConstants.Y);
                    po.setReportUser(usersId);
                    po.setReportTime(PlatformDateUtils.getCurrentTimestamp());
                    reportPOS.add(po);
                }
            }
            SendDataRes sendDataRes = null;
            if ("41".equals(taskId)) {
                sendDataRes = combinationData(anEnum, reportPOList);
            } else {
                sendDataRes = combinationData(anEnum, reportPOS);
            }
            String postData = JSON.toJSONString(sendDataRes, SerializerFeature.WriteMapNullValue);
            logger.info("==========" + taskId + taskName + " ,发送数据为【{}】", postData);
            String url = "https://fxpc.mem.gov.cn/task_back/api/v1/task_inital/jindu_gather";
            HttpURLConnection conn = null;
            try {
                byte[] byteArray = postData.getBytes(StandardCharsets.UTF_8);
                //忽略证书
                SSLContext sslcontext = SSLContext.getInstance("SSL", "SunJSSE");
                sslcontext.init(null, new TrustManager[]{new MyX509TrustManager()}, new java.security.SecureRandom());
                URL serverUrl = new URL(url);
                //忽略
                HostnameVerifier ignoreHostnameVerifier = new HostnameVerifier() {
                    public boolean verify(String s, SSLSession sslsession) {
                        //System.out.println("WARNING: Hostname is not matched for cert.");
                        return true;
                    }
                };
                HttpsURLConnection.setDefaultHostnameVerifier(ignoreHostnameVerifier);
                HttpsURLConnection.setDefaultSSLSocketFactory(sslcontext.getSocketFactory());
                conn = (HttpURLConnection) serverUrl.openConnection();
                conn.setRequestMethod("POST");
                conn.setRequestProperty("token", "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJkZXBUeXBlIjo5LCJrZXkiOiJneHNuXzVaeXc2WnlIOSIsImlhdCI6MTYxNzE1NzgxNn0.dkb4tqvCmexrLLZUd1nOiwfV_fKTdQFjHCYWkTreatQ");
                conn.setRequestProperty("Content-Type", "application/json");
                //必须设置false，否则会自动redirect到重定向后的地址
                conn.setInstanceFollowRedirects(false);
                //设置参数
                conn.setDoInput(true);
                conn.setDoOutput(true);
                OutputStream out = conn.getOutputStream();
                out.write(byteArray);
                out.close();
                conn.connect();
                String result = getReturn(conn);
                logger.info("==========" + taskName + " ,接收结果为:【{}】", result);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        logger.info("##########################   上报进度发送结束");
    }

    /*请求url获取返回的内容*/
    private String getReturn(HttpURLConnection connection) throws IOException {
        StringBuilder buffer = new StringBuilder();
        //将返回的输入流转换成字符串
        try (InputStream inputStream = connection.getInputStream();
             InputStreamReader inputStreamReader = new InputStreamReader(inputStream, StandardCharsets.UTF_8);
             BufferedReader bufferedReader = new BufferedReader(inputStreamReader);) {
            String str;
            while ((str = bufferedReader.readLine()) != null) {
                buffer.append(str);
            }
            return buffer.toString();
        }
    }

    @Override
    public void updatePcSchedule(List<JobScheduleReportVO> vos, String usersId) {
        Map<String, String> voMap = new HashMap<>();
        for (JobScheduleReportVO vo1 : vos) {
            String quantity = vo1.getQuantity();
            String percentage = vo1.getPercentage();
            String key = vo1.getTaskCode() + "," + vo1.getDivisionCode();
            String value = voMap.get(key);
            if (StringUtils.isEmpty(value) || "null".equals(value)) {
                if (StringUtils.isNotEmpty(quantity) && !"null".equals(quantity)) {
                    voMap.put(key, quantity);
                } else if (StringUtils.isNotEmpty(percentage) && !"null".equals(percentage)) {
                    voMap.put(key, "-" + percentage);
                }
            } else {
                if (value.contains("-")) {
                    voMap.put(key, quantity + value);
                } else {
                    voMap.put(key, value + "-" + percentage);
                }
            }
        }
        List<JobScheduleReportPO> reportPOList = jobScheduleRepository.findAll();
        List<JobScheduleReportPO> updatePos = new ArrayList<>();
        List<JobScheduleReportPO> savePos = new ArrayList<>();
        for (String key : voMap.keySet()) {
            String taskCode = key.split(",")[0];
            ScheduleReportEnum reportEnum = ScheduleReportEnum.getById(taskCode);
            String divisionCode = key.split(",")[1];
            String divisionName = null;
            for (DivisionVo divisionVo : provinceList) {
                if (divisionCode.equals(divisionVo.getProvinceCode())) {
                    divisionName = divisionVo.getProvinceName();
                    break;
                }
            }
            String value = voMap.get(key);
            String quantity = value.split("-")[0];
            String percentage = null;
            if (value.contains("-")) {
                percentage = value.split("-")[1];
            }
            JobScheduleReportPO reportPO = null;
            for (JobScheduleReportPO po : reportPOList) {
                if (po.getTaskCode().equals(taskCode) && po.getDivisionCode().equals(divisionCode)) {
                    reportPO = po;
                    break;
                }
            }
            if (reportPO == null) {
                reportPO = new JobScheduleReportPO();
                reportPO.setId(UUIDGenerator.getUUID());
                reportPO.setTaskCode(taskCode);
                reportPO.setTaskName(reportEnum.getTaskName());
                if (StringUtils.isNotEmpty(quantity) && !"null".equals(quantity)) {
                    if("nan".equals(quantity.toLowerCase())) {
                        reportPO.setQuantity(null);
                    }else {
                        reportPO.setQuantity(quantity);
                    }
                }
                if (StringUtils.isNotEmpty(percentage) && !"null".equals(percentage)) {
                    if("nan".equals(percentage.toLowerCase())) {
                        reportPO.setPercentage(null);
                    }else {
                        reportPO.setPercentage(percentage);
                    }
                }
                reportPO.setDivisionCode(divisionCode);
                reportPO.setDivisionName(divisionName);
                reportPO.setCreateTime(PlatformDateUtils.getCurrentTimestamp());
                reportPO.setCreateUser(usersId);
                reportPO.setIsValid(PlatformConstants.Y);
                reportPO.setIsHasReport(PlatformConstants.N);
                reportPO.setReportId(reportEnum.getReportId());
                savePos.add(reportPO);
            } else {
                if (StringUtils.isNotEmpty(quantity) && !"null".equals(quantity)) {
                    if("nan".equals(quantity.toLowerCase())) {
                        reportPO.setQuantity(null);
                    }else {
                        reportPO.setQuantity(quantity);
                    }
                }
                if (StringUtils.isNotEmpty(percentage) && !"null".equals(percentage)) {
                    if("nan".equals(percentage.toLowerCase())) {
                        reportPO.setPercentage(null);
                    }else {
                        reportPO.setPercentage(percentage);
                    }
                }
                reportPO.setUpdateUser(usersId);
                reportPO.setUpdateTime(PlatformDateUtils.getCurrentTimestamp());
                updatePos.add(reportPO);
            }
        }
        jobScheduleNativeRepository.batchSave(savePos);
        jobScheduleNativeRepository.batchUpdate(updatePos);
    }

    @Override
    public void saveAll(List<JobScheduleReportPO> poList) {
        jobScheduleRepository.saveAll(poList);
    }
}
